from ..handlers.inheritHandler import Base
from ..rig import register
from ..module import syncFile, syncSqlite

import datetime

db = syncSqlite.Component
fc = syncFile.Component

api = register.Router(prefix="/api")

PER_NUM = 20


class Pagination(Base):

    async def pagination(self, count_func, output_func):
        global PER_NUM
        per_num = PER_NUM
        page = self.get_query_argument("page", '0')
        page = int(page)
        if page < 1:
            page = 1

        with db() as conn:
            count = count_func(conn)
            total = (count // per_num) + int((count % per_num) > 0)
            if total < page:
                page = total

            if page == 0:
                result = []
            else:
                result = output_func(conn, (page - 1) * per_num, per_num)

        self.write_dict({
            "total": total,
            "current": page,
            "perNum": per_num,
            "result": result
        })


@api.route()
class BoxesHandler(Pagination):

    async def get(self):
        """

        获取盒子列表::

            /api/boxes

        """
        await self.pagination(
            lambda conn: conn.output_sql("select count(id) as count from box;")[0]["count"],
            lambda conn, x, y: conn.output_sql("select *,'box' as type from box limit {},{}".format(x, y))
        )


@api.route(url=r"/box/([a-z0-9\-]*?)")
class BoxHandler(Base):

    # @override
    async def get(self, *args):
        """

        获取盒子信息::

            /api/box/(:id)

        """
        box_id = args[0]
        with db() as conn:
            result = conn.select_tcw("box", where="id=?", where_arg=[box_id])
        if len(result) < 1:
            self.throw(404)
        self.write_dict(result[0])

    # @override
    async def post(self, *args):
        """

        增加盒子::

            /api/box/(:id)

        """
        box_id = args[0]
        fpc = fc("box_image", top_path="statics")
        fpc.ensure_dir(fpc.root_path)
        name, source_ext, save_path = fpc.receive_file(self.request.files)

        with db() as conn:
            affect = conn.insert_tc("box", {
                "id": box_id,
                "name": self.get_body_argument("name", "box"),
                "date": datetime.date.today().strftime("%Y-%m-%d"),
                "desc": self.get_body_argument("desc", ""),
                "parent": box_id,
                "image": save_path,
                "keywords": self.get_body_argument("keywords", "")
            })
        if affect.status:
            self.write_ok()
        else:
            fpc.rollback_receive_file(save_path)
            self.throw(400, "sql失败")

    # @override
    async def put(self, *args):
        """

         修改盒子信息::

             /api/box/(:id)

         """
        box_id = args[0]
        update_dict = self.get_body_argument_from(["name", "desc", "keywords"])

        if not update_dict:
            self.throw(200, "no update")

        with db() as conn:
            conn.update_tcw("box", update_dict, where="id=?", where_arg=[box_id])

        self.write_ok()

    # @override
    async def delete(self, *args):
        """

         删除盒子::

             /box/(:id)

         """
        box_id = args[0]
        with db() as conn:
            conn.delete_tw("box", "id=?", where_arg=[box_id])
        self.write_ok()


@api.route(url=r"/box/([a-z0-9\-]*?)/boxes")
class BoxBoxesHandler(Pagination):

    async def get(self, *args):
        """

        获取盒子里面所有子盒子，支持分页

        """
        parent_box_id = args[0]

        await self.pagination(
            lambda conn: conn.output_sql(
                "select count(id) as count from box where parent=? and parent <> id;",
                arg_list=[parent_box_id])[0]["count"],
            lambda conn, x, y: conn.output_sql(
                "select *,'box' as type from box where parent=? and parent <> id ORDER BY date desc limit {},{}".format(
                    x, y),
                arg_list=[parent_box_id]
            )
        )


@api.route(url=r"/box/([a-z0-9\-]*?)/objects")
class BoxObjectsHandler(Pagination):

    async def get(self, *args):
        """

        获取盒子里面所有物品，支持分页

        """
        parent_box_id = args[0]
        await self.pagination(
            lambda conn: conn.output_sql(
                "select count(id) as count from object where box_id=?;",
                arg_list=[parent_box_id])[0]["count"],
            lambda conn, x, y: conn.output_sql(
                "select *,'object' as type from object where box_id=? ORDER BY date desc limit {},{}".format(x, y),
                arg_list=[parent_box_id]
            )
        )


@api.route(url=r"/object/(\d*)")
class ObjectHandler(Base):

    # @override
    async def get(self, *args):
        """

        获取物品信息::

            /object/(:id)

        """
        oid = args[0]
        with db() as conn:
            result = conn.select_tcw("object", where="id=?", where_arg=[oid])
        if len(result) < 1:
            self.throw(404)
        else:
            self.write_dict(result[0])

    # @override
    async def put(self, *args):
        """

         修改物品信息::

             /object/(:id)

         """
        oid = args[0]
        update_dict = self.get_argument_from(["count", "desc", "name", "keywords"])
        if not update_dict:
            self.throw(200, log_message="无更改")

        with db() as conn:
            conn.update_tcw("object", update_dict, where="id=?", where_arg=[oid])

        self.write_ok()

    # @override
    async def delete(self, *args):
        """

         删除物品::

             /box/(:id)

         """
        oid = args[0]
        with db() as conn:
            conn.delete_tw("object", where="id=?", where_arg=[oid])

        self.write_ok()


@api.route(url=r"/box/([a-z0-9\-]*?)/object")
class BoxObjectHandler(Base):

    async def post(self, *args):
        """

        盒子增加商品

        """
        box_id = args[0]
        object_content = self.get_argument_from(["count", "desc", "name", "keywords"])

        object_content["box_id"] = box_id

        fpc = fc("object_image", "statics")
        fpc.ensure_dir(fpc.root_path)
        object_content["image"] = fpc.receive_file(self.request.files)[2]

        object_content["date"] = datetime.date.today().strftime("%Y-%m-%d")

        with db() as conn:
            affect = conn.insert_tc("object", object_content)

        if affect.status:
            self.write_ok()
        else:
            self.throw(400, log_message="sql失败")


@api.route(url=r"/box/([a-z0-9\-]*?)/box")
class BoxBoxHandler(Base):

    async def post(self, *args):
        """

        盒子增加盒子

        """
        box_id = args[0]
        child_box_id = self.get_body_argument("box_id")
        with db() as conn:
            conn.update_tcw("box", {"parent": box_id}, where="id=?", where_arg=[child_box_id])
        self.write_ok()


@api.route(url=r"/search")
class SearchObjectHandler(Pagination):

    async def get(self):
        """

        搜索物品

        """
        query = "%{}%".format(self.get_query_argument("query"))

        await self.pagination(
            lambda conn: conn.output_sql(
                "select count(id) as count from object where keywords like ? or name like ? or desc like ?;",
                arg_list=[query, query, query])[0]["count"],
            lambda conn, x, y: conn.output_sql(
                "select *,'object' as type from object where keywords like ? or "
                "name like ? or desc like ? ORDER BY date desc limit {},{}".format(x, y),
                arg_list=[query, query, query]
            )
        )
